<template>
  <ThreeFrame
    :obj3Ds = "obj3Ds"
  ></ThreeFrame>
</template>

<script setup>
import * as THREE from 'three';
import { TextGeometry } from 'three/examples/jsm/geometries/TextGeometry'
import ThreeFrame from './ThreeFrame.vue'
import { ref, onMounted } from 'vue'
import * as fontUtils from '../utils/fontUtils'
const emits = defineEmits(['encoder-attention-selected']);

const arrowLength = 0.5
const boxWidth = 0.5
const boxHeight = 2
const boxDepth = 1

let xMultiHeadAttention = 0
let xAddNorm1 = 0
let xFeedForward = 0
let xAddNorm2 = 0

const obj3Ds = ref([])

function fontLoaded(font) {
  let textObjs = []
  // 创建文字

  let text = fontUtils.createTextObjectOnBoxFront(font, 'Multi Head Attention', xMultiHeadAttention, true, boxDepth)
  textObjs.push(text)

  text = fontUtils.createTextObjectOnBoxFront(font, 'Add & Norm', xAddNorm1, true, boxDepth)
  textObjs.push(text)

  text = fontUtils.createTextObjectOnBoxFront(font, 'Feed Forward', xFeedForward, true, boxDepth)
  textObjs.push(text)

  text = fontUtils.createTextObjectOnBoxFront(font, 'Add & Norm', xAddNorm2, true, boxDepth)
  textObjs.push(text)

  text = fontUtils.createTextObject(font, 'Encoder Block', fontUtils.figureFontSize, fontUtils.textObjectHeight, fontUtils.textColor, -1, -1.3, 0)
  textObjs.push(text)

  text = fontUtils.createTextObject(font, '<Block Input>', fontUtils.textFontSize, fontUtils.textObjectHeight, fontUtils.textColor, -3.5, 0, 0)
  textObjs.push(text)

  text = fontUtils.createTextObject(font, '<Block Output>', fontUtils.textFontSize, fontUtils.textObjectHeight, fontUtils.textColor, 2.5, 0, 0)
  textObjs.push(text)

  // scene.add(text1);
  obj3Ds.value = [...obj3Ds.value, ...textObjs]
}


function initObj3Ds() {
  let objects = []

  let offsetX = -2.5

  // 添加左侧箭头
  let arrow = new THREE.ArrowHelper(
    new THREE.Vector3(1, 0, 0),
    new THREE.Vector3(offsetX, 0, 0),
    arrowLength,
    0xff00ff
  );
  objects.push(arrow)

  offsetX += arrowLength
  // console.log('offsetX', offsetX)

  // 添加self attention 盒子
  let box = new THREE.Mesh(
    new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth),
    new THREE.MeshPhongMaterial({ color: 0xff0000 })
  );
  xMultiHeadAttention = offsetX + boxWidth/2
  box.position.x = xMultiHeadAttention;
  objects.push(box)

  box.onSelected = () => {
    emits('encoder-attention-selected')
  }

  offsetX += boxWidth
  // console.log('offsetX', offsetX)

  arrow = new THREE.ArrowHelper(
    new THREE.Vector3(1, 0, 0),
    new THREE.Vector3(offsetX, 0, 0),
    arrowLength,
    0xff00ff
  );
  objects.push(arrow)

  offsetX += arrowLength
  // console.log('offsetX', offsetX)

  // 添加Add & Norm 盒子
  box = new THREE.Mesh(
    new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth),
    new THREE.MeshPhongMaterial({ color: 0x00ff00 })
  );
  xAddNorm1 = offsetX + boxWidth/2;
  box.position.x = xAddNorm1
  objects.push(box)

  offsetX += boxWidth
  // console.log('offsetX', offsetX)

  arrow = new THREE.ArrowHelper(
    new THREE.Vector3(1, 0, 0),
    new THREE.Vector3(offsetX, 0, 0),
    arrowLength,
    0xff00ff
  );
  objects.push(arrow)

  offsetX += arrowLength
  // console.log('offsetX', offsetX)

  // 添加Feed Forward 盒子
  box = new THREE.Mesh(
    new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth),
    new THREE.MeshPhongMaterial({ color: 0x00ff00 })
  );
  xFeedForward = offsetX + boxWidth/2;
  box.position.x = xFeedForward
  objects.push(box)

  offsetX += boxWidth
  // console.log('offsetX', offsetX)

  arrow = new THREE.ArrowHelper(
    new THREE.Vector3(1, 0, 0),
    new THREE.Vector3(offsetX, 0, 0),
    arrowLength,
    0xff00ff
  );
  objects.push(arrow)

  offsetX += arrowLength
  // console.log('offsetX', offsetX)

  // 添加Add & Norm 盒子
  box = new THREE.Mesh(
    new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth),
    new THREE.MeshPhongMaterial({ color: 0x00ff00 })
  );
  xAddNorm2 = offsetX + boxWidth/2;
  box.position.x = xAddNorm2
  objects.push(box)

  offsetX += boxWidth
  // console.log('offsetX', offsetX)

  arrow = new THREE.ArrowHelper(
    new THREE.Vector3(1, 0, 0),
    new THREE.Vector3(offsetX, 0, 0),
    arrowLength,
    0xff00ff
  );
  objects.push(arrow)

  offsetX += arrowLength
  // console.log('offsetX', offsetX)

  // // 创建一个平面几何体
  // let geometry = new THREE.PlaneGeometry(1.5, 1.2);
  // // 加载图片
  // let textureLoader = new THREE.TextureLoader();
  // let texture = textureLoader.load('/transformer-encoder-mhattention-norm.png');
  // // 创建一个材质，并将图片应用于材质
  // let material = new THREE.MeshBasicMaterial({ map: texture });
  // // 创建一个网格，并将平面几何体和材质应用于网格
  // let planeMeshAttn = new THREE.Mesh(geometry, material);

  // planeMeshAttn.position.set(-1.25, 1.6 + 0.1, 0)

  // objects.push(planeMeshAttn)

  // // 创建一个平面几何体
  // geometry = new THREE.PlaneGeometry(1.5, 1.0);
  // // 加载图片
  // textureLoader = new THREE.TextureLoader();
  // texture = textureLoader.load('/transformer-encoder-ff-norm.png');
  // // 创建一个材质，并将图片应用于材质
  // material = new THREE.MeshBasicMaterial({ map: texture });
  // // 创建一个网格，并将平面几何体和材质应用于网格
  // let planeMeshFF = new THREE.Mesh(geometry, material);

  // planeMeshFF.position.set(0.75, 1.5 + 0.1, 0)

  // objects.push(planeMeshFF)

  return objects
}

onMounted(() => {
  console.log('TransformerEncoderBlock onMounted')
  obj3Ds.value = initObj3Ds()
  fontUtils.loadFont(fontLoaded)
})

</script>